#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace KLib.Graphics
{
    public class TextureGenerator
    {
        #region Fields
        private static GraphicsDevice graphics;
        private static Texture2D texture;
        #endregion

        #region Properties

        #endregion

        #region Initialization

        public TextureGenerator()
        {
        }

        public static void Initalize(GraphicsDevice graphicsDevice)
        {
            graphics = graphicsDevice;
        }

        #endregion

        #region Methods

        #region Generate Rectangle

        public static Texture2D GenerateRectangle(Rectangle rectangle, Color color, Color boarderColor,int boarderWidth)
        {
            return GenerateRectangle(rectangle.Width, rectangle.Width, color, boarderColor, boarderWidth, 1, 1);
        }
        /// <summary>
        /// Generates a Rectangular Texture
        /// </summary>
        /// <param name="width">The width (in pixels) of the rectangle</param>
        /// <param name="height">The height (in pixels) of the rectangle</param>
        /// <param name="color">The Color of the rectangle</param>
        public static Texture2D GenerateRectangle(int width, int height, Color color)
        {
            return GenerateRectangle(width, height, color, Color.TransparentBlack, 0, 1, 1);
        }
        /// <summary>
        /// Generates a Rectangular Texture
        /// </summary>
        /// <param name="width">The width (in pixels) of the rectangle</param>
        /// <param name="height">The height (in pixels) of the rectangle</param>
        /// <param name="color">The Color of the rectangle</param>
        /// <param name="boarderColor">The Color of the boarder of the rectangle (has a boarderWidth of 1 pixel)</param>
        public static Texture2D GenerateRectangle(int width, int height, Color color, Color boarderColor)
        {
            return GenerateRectangle(width, height, color, boarderColor, 1, 1, 1);
        }
        /// <summary>
        /// Generates a Rectangular Texture
        /// </summary>
        /// <param name="width">The width (in pixels) of the rectangle</param>
        /// <param name="height">The height (in pixels) of the rectangle</param>
        /// <param name="color">The Color of the rectangle</param>
        /// <param name="boarderColor">The Color of the boarder of the rectangle (has a boarderWidth of 1 pixel)</param>
        /// <param name="boarderWidth">The width (in pixels) of the boarder of the rectangle</param>
        public static Texture2D GenerateRectangle(int width, int height, Color color, Color boarderColor, int boarderWidth)
        {
            return GenerateRectangle(width, height, color, boarderColor, boarderWidth, 1, 1);
        }

        /// <summary>
        /// Generates a Rectangular Texture
        /// </summary>
        /// <param name="width">The width (in pixels) of the rectangle</param>
        /// <param name="height">The height (in pixels) of the rectangle</param>
        /// <param name="color">The Color of the rectangle</param>
        /// <param name="boarderColor">The Color of the boarder of the rectangle (has a boarderWidth of 1 pixel)</param>
        /// <param name="boarderWidth">The width (in pixels) of the boarder of the rectangle</param>
        /// <param name="alpha">The Transparency of the inside of the rectangle (1=Opaque, 0=Transparent) (boarder will be fully Opaque)</param>
        public static Texture2D GenerateRectangle(int width, int height, Color color, Color boarderColor, int boarderWidth, float alpha)
        {
            return GenerateRectangle(width, height, color, boarderColor, boarderWidth, alpha, 1);
        }

        /// <summary>
        /// Generates a Rectangular Texture
        /// </summary>
        /// <param name="width">The width (in pixels) of the rectangle</param>
        /// <param name="height">The height (in pixels) of the rectangle</param>
        /// <param name="color">The Color of the rectangle</param>
        /// <param name="boarderColor">The Color of the boarder of the rectangle (has a boarderWidth of 1 pixel)</param>
        /// <param name="boarderWidth">The width (in pixels) of the boarder of the rectangle</param>
        /// <param name="alpha">The Transparency of the inside of the rectangle (1=Opaque, 0=Transparent)</param>
        /// <param name="boarderAlpha">The Transparency of the boarder of the rectangle (1=Opaque, 0=Transparent)</param>
        public static Texture2D GenerateRectangle(int width, int height, Color color, Color boarderColor, int boarderWidth, float alpha, float boarderAlpha)
        {
            //Quick Hack fix - This should do something other than return a useless texture...
            if (width <= 0 || height <= 0) return GenerateRectangle(1, 1, color, boarderColor, boarderWidth, alpha, boarderAlpha);

            Color colorWithAlpha = new Color(color.R, color.G, color.B, (byte)(255 * alpha));
            Color boarderColorWithAlpha = new Color(boarderColor.R, boarderColor.G, boarderColor.B, (byte)(255 * boarderAlpha));
            texture = new Texture2D(graphics, width, height, 1, TextureUsage.None, SurfaceFormat.Color);
            Color[] texColors = new Color[texture.Width * texture.Height];
            for (int x = 0; x < texture.Width; x++)
            {
                for (int y = 0; y < texture.Height; y++)
                {
                    if (x < boarderWidth
                        || (x >= texture.Width - boarderWidth && x <= texture.Width)
                        || (y < boarderWidth)
                        || (y >= texture.Height - boarderWidth && y <= texture.Height))
                    {
                        texColors[x + y * width] = boarderColorWithAlpha;
                    }
                    else
                        texColors[x + y * width] = colorWithAlpha;
                }
            }
            texture.SetData<Color>(texColors);
            return texture;
        }
        #endregion

        #region Generate Circle
        public static Texture2D GenerateCircle(int radius, Color color)
        {
            return GenerateCircle(radius, color, Color.White, 0, color.A / 255f, 0);
        }

        public static Texture2D GenerateCircle(int radius, Color color, Color boarderColor)
        {
            return GenerateCircle(radius, color, boarderColor, 1, color.A / 255f, boarderColor.A / 255f);
        }

        public static Texture2D GenerateCircle(int radius, Color color, Color boarderColor, float boarderWidth)
        {
            return GenerateCircle(radius, color, boarderColor, boarderWidth, color.A / 255f, boarderColor.A / 255f);
        }

        public static Texture2D GenerateCircle(int radius, Color color, Color boarderColor, float boarderWidth, float alpha, float boarderAlpha)
        {
            int x = 0;
            int y = -1;
            int diameter = (radius + 2) * 2;
            Vector2 center = new Vector2((diameter - 1) / 2f, (diameter - 1) / 2f);

            texture = new Texture2D(graphics, diameter, diameter, 1, TextureUsage.None, SurfaceFormat.Color);
            Color[] colors = new Color[diameter * diameter];

            for (int i = 0; i < colors.Length; i++)
            {
                if (i % diameter == 0) y++;
                x = i % diameter;

                Vector2 distance = new Vector2(Math.Abs(center.X - x), Math.Abs(center.Y - y));

                Vector2 diff = new Vector2(x, y) - center;

                float length = diff.Length();

                if (length > radius)
                    colors[i] = Color.TransparentBlack;

                else if (length > radius - boarderWidth)
                    colors[i] = new Color(boarderColor.R, boarderColor.G, boarderColor.B, (byte)(255 * boarderAlpha));
                else
                    colors[i] = new Color(color.R, color.G, color.B, (byte)(255 * alpha));
            }

            texture.SetData<Color>(colors);

            return texture;
        }
        #endregion

        #endregion

        #region Helper Methods

        #endregion
    }
}
